package oop.core.skill;

import oop.core.Scheduler;
import oop.core.IDUpdateable;
import oop.core.map.GameMap;
import oop.core.map.Location;
import oop.core.map.TemporalLocation;

import java.util.*;
/**
 * SkillHandler communicates with the SkillMediatorFromHotkey
 * and actually performs the logic of putting the SkillObjects
 * on the map along with registering them with the scheduler.
 */
public class SkillHandler implements IDUpdateable{
	private Scheduler scheduler;
	private GameMap gameMap;
	private Map<Long, SkillObjectWithLocation> spawns;
	private Map<Long, SkillObjectWithLocation> kills;
	private Map<Location, SkillObject> mapSkillObjects;
	private static long id = 0;
	
	/**
	 * SkillHandler constructor method.
	 * @param scheduler
	 * @param gameMap
	 */
	public SkillHandler(Scheduler scheduler, GameMap gameMap){
		this.scheduler = scheduler;
		this.gameMap = gameMap;
		this.spawns = new HashMap<Long, SkillObjectWithLocation>();
		this.kills = new HashMap<Long, SkillObjectWithLocation>();
		this.mapSkillObjects = gameMap.getSkillObjectMap();
	}

	/**
	 * Implements IDUpdatable interface's update(long id)
	 * Populates the map's skillObject with a skill
	 * or removes the skill when updated.
	 * @param id
	 */
	public void update(long id){
		//System.out.println("update id = " + id);
		SkillObjectWithLocation ret = spawns.get(id);
		if(ret == null){
			SkillObjectWithLocation obj = kills.remove(id);
			Location loc = obj.getLocation();
			mapSkillObjects.remove(loc);
			//System.out.println(loc + " SkillObject removed at this location");
		}
		else{
			SkillObjectWithLocation obj = spawns.remove(id);
			SkillObject newSkillObject = obj.getSkillObject();
			Location loc = obj.getLocation();
			mapSkillObjects.put(loc,newSkillObject);
			//System.out.println(newSkillObject.getImageID() + " Put On Map");
		}
	}
	
	/**
	 * Queries the skill description s for propogations
	 * based on a location and direction.  Propogations
	 * derive spawn and kill times of Skill Object
	 * instances.  Registers them with the scheduler.
	 * @param s
	 * @param loc
	 * @param direction
	 */
	public void register(ActiveSkill s, Location loc, int direction){
		//System.out.println("REGISTRAR");
		List<TemporalLocation> ret = s.calculateLocationSet(loc, direction);
		for(TemporalLocation t : ret){
			long id = getID();
			float e = s.getEffect();
			Location local = t.getLocation();
			
			double dist = Location.distance(local, loc);
			
			if( dist != 0 )
			{
				e /= dist;
			}
			
			SkillObjectWithLocation obj = new SkillObjectWithLocation(new SkillObject(s, e),local);
			spawns.put(id, obj);
			kills.put(id, obj);			
			scheduler.register(this,t.getTime(),(int)id);
			scheduler.register(this,t.getTime()+s.getLifeTime(),(int)id);
			//System.out.println("Register [" + id + "] @ " + t.getTime() + ", " + (t.getTime() + s.getLifeTime()));
		}
	}
	
	/**
	 * get/set methods
	 */
	public static long getID(){
		return id++;
	}
	
	public Scheduler getScheduler() {
		return scheduler;
	}

	public void setScheduler(Scheduler scheduler) {
		this.scheduler = scheduler;
	}

	public GameMap getGameMap() {
		return gameMap;
	}

	public void setGameMap(GameMap gameMap) {
		this.gameMap = gameMap;
	}
}
